#include "MephistoCAM.h"

int init_ad9508_config( AD9508_Config *cfg ){

    cfg->reg_num = AD9508_REG_NUM;

    cfg->reg_addr           = (uint32_t*)malloc(sizeof(uint32_t)*cfg->reg_num);
    cfg->reg_data           = (uint32_t*)malloc(sizeof(uint32_t)*cfg->reg_num);
    cfg->reg_data_default   = (uint32_t*)malloc(sizeof(uint32_t)*cfg->reg_num);

    cfg->reg_addr[0]            = 0X00;
    cfg->reg_data_default[0]    = 0x00;
    
    cfg->reg_addr[1]            = 0X12;
    cfg->reg_data_default[1]    = 0x02;
    
    cfg->reg_addr[2]            = 0X13;
    cfg->reg_data_default[2]    = 0x00;
    
    cfg->reg_addr[3]            = 0X14;
    cfg->reg_data_default[3]    = 0x01;
    
    cfg->reg_addr[4]            = 0X15;
    cfg->reg_data_default[4]    = 0x00;
    
    cfg->reg_addr[5]            = 0X16;
    cfg->reg_data_default[5]    = 0x00;
    
    cfg->reg_addr[6]            = 0X17;
    cfg->reg_data_default[6]    = 0x00;
    
    cfg->reg_addr[7]            = 0X18;
    cfg->reg_data_default[7]    = 0x00;
    
    cfg->reg_addr[8]            = 0X19;
    cfg->reg_data_default[8]    = 0x14;
    
    cfg->reg_addr[9]            = 0X1A;
    cfg->reg_data_default[9]    = 0x00;
    
    cfg->reg_addr[10]           = 0X1B;
    cfg->reg_data_default[10]   = 0x00;
    
    cfg->reg_addr[11]           = 0X1C;
    cfg->reg_data_default[11]   = 0x00;
    
    cfg->reg_addr[12]           = 0X1D;
    cfg->reg_data_default[12]   = 0x00;
    
    cfg->reg_addr[13]           = 0X1E;
    cfg->reg_data_default[13]   = 0x00;
    
    cfg->reg_addr[14]           = 0X1F;
    cfg->reg_data_default[14]   = 0x14;
    
    cfg->reg_addr[15]           = 0X20;
    cfg->reg_data_default[15]   = 0x00;
    
    cfg->reg_addr[16]           = 0X21;
    cfg->reg_data_default[16]   = 0x00;
    
    cfg->reg_addr[17]           = 0X22;
    cfg->reg_data_default[17]   = 0x00;
    
    cfg->reg_addr[18]           = 0X23;
    cfg->reg_data_default[18]   = 0x00;
    
    cfg->reg_addr[19]           = 0X24;
    cfg->reg_data_default[19]   = 0x00;
    
    cfg->reg_addr[20]           = 0X25;
    cfg->reg_data_default[20]   = 0x14;
    
    cfg->reg_addr[21]           = 0X26;
    cfg->reg_data_default[21]   = 0x00;
    
    cfg->reg_addr[22]           = 0X27;
    cfg->reg_data_default[22]   = 0x00;
    
    cfg->reg_addr[23]           = 0X28;
    cfg->reg_data_default[23]   = 0x00;
    
    cfg->reg_addr[24]           = 0X29;
    cfg->reg_data_default[24]   = 0x00;
    
    cfg->reg_addr[25]           = 0X2A;
    cfg->reg_data_default[25]   = 0x00;
    
    cfg->reg_addr[26]           = 0X2B;
    cfg->reg_data_default[26]   = 0x14;
    
    cfg->reg_addr[27]           = 0X2C;
    cfg->reg_data_default[27]   = 0x00;


    int i;
    for( i=0; i<cfg->reg_num; i++ ) {
        cfg->reg_data[i] = 0;
    }

    cfg->reg_data[21]   = 144;

    return 0;
}

int read_ad9508_config( AD9508_Config *cfg, char *cfg_ini, char *section ){

    dictionary *ini = iniparser_load( cfg_ini );

    if( NULL == ini ){
        printf("> (ad9508) failed to open: %s\n", cfg_ini);
        exit(0);
    }

    char sec_param[64];

    int i;
    for( i=0; i<cfg->reg_num; i++ ){
        sprintf(sec_param, "%s:0X%02X", section, cfg->reg_addr[i]);
        cfg->reg_data[i] = iniparser_getint( ini, sec_param, cfg->reg_data_default[i] );
        // usleep(10000);
        // printf("> i = %2d, loaded %s , value = %d\n", i, sec_param, cfg->reg_data[i]);
    }

    iniparser_freedict( ini );

    return 0;
}

int free_ad9508_config( AD9508_Config *cfg ){
    free( cfg->reg_addr );
    free( cfg->reg_data );
    free( cfg->reg_data_default );
    return 0;
}

int print_ad9508_config( AD9508_Config *cfg ){

    int i;

    printf("> *****************************************\n");
    printf("> address and values of AD9508 registers:\n");
    printf("> reg_addr    reg_data   [reg_data_default]\n");

    for( i=0; i<cfg->reg_num; i++ ){
        printf("\t0X%02x\t%4d \t  [ 0X%02x  %4d] \n", 
                cfg->reg_addr[i],
                cfg->reg_data[i],
                cfg->reg_data_default[i],
                cfg->reg_data_default[i]
                );
        
        // print_as_bin(cfg->reg_data[i]);
    }

    printf("> *****************************************\n");

    return 0;
}

int update_ad9508_config( AD9508_Config *cfg ){

    printf("**** NOT IMPLEMENTED YET!!! ****\n");

    return 0;
}

int config_ad9508_via_SPI(  uint32_t *gpio_reg,
                            uint32_t *gpio2_reg,
                            uint32_t *gpio_in_reg,
                            SPI_CONFIG *spi_config,
                            AD9508_Config *cfg ){

    SPI_DATA *spi_data = (SPI_DATA*)malloc(sizeof(SPI_DATA));
    spi_data_alloc( spi_data, cfg->reg_num );

    int i=0;
    for( i=0; i<cfg->reg_num; i++ ){
        spi_data_set_LS( spi_data,
                         i,
                         cfg->reg_addr[i],
                         cfg->reg_data[i],
                         8 );   // 数据位共计8bits

        // printf(">@debug I = %2d, reg_data = %d\n", i, cfg->reg_data[i]);
    }

    printf("> (ad9508) finished setting spi_data\n");

    send_spi_data(  gpio_reg,
                    gpio2_reg,
                    gpio_in_reg,
                    spi_config, 
                    spi_data );

    spi_data_free( spi_data );

    return 0;
}

int config_a_ad9508_reg_via_SPI(uint32_t *gpio_reg,
                                uint32_t *gpio2_reg,
                                uint32_t *gpio_in_reg,
                                SPI_CONFIG *spi_config,
                                AD9508_Config *cfg,
                                char *reg_addr,
                                uint32_t reg_data ){

    SPI_DATA *spi_data = (SPI_DATA*)malloc(sizeof(SPI_DATA));
    spi_data_alloc( spi_data, 1 );

    int i, idx=0;

    for( i=0; i<cfg->reg_num; i++ ){
        char s_addr[8];
        sprintf(s_addr, "0X%02X", cfg->reg_addr[i]);

        if( strcmp(reg_addr, s_addr) == 0 ){
            idx = i;
            break;
        }
    }


    spi_data_set_LS( spi_data,
                     0,
                     cfg->reg_addr[idx],
                     reg_data,
                     8 );

    // printf(">@debug I = %2d, reg_addr = 0X%02X, reg_data = %d\n", idx, cfg->reg_addr[idx], reg_data);

    send_spi_data(  gpio_reg,
                    gpio2_reg,
                    gpio_in_reg,
                    spi_config, 
                    spi_data );

    spi_data_free( spi_data );

    return 0;
}

int read_a_ad9508_reg_via_SPI(  uint32_t *gpio_reg,
                                uint32_t *gpio2_reg,
                                uint32_t *gpio_in_reg,
                                SPI_CONFIG *spi_config,
                                AD9508_Config *cfg,
                                uint32_t reg_addr ){

    SPI_DATA *spi_data = (SPI_DATA*)malloc(sizeof(SPI_DATA));
    spi_data_alloc( spi_data, 1 );

    uint32_t reg_data = 0;
    uint32_t reg_addr_xx = 0;

    reg_addr_xx |= (1<<15);
    reg_addr_xx |= reg_addr;

    spi_data_set_LS( spi_data,
                     0,
                     reg_addr_xx,
                     reg_data,
                     8 );

    // printf(">@debug I = %2d, reg_addr = 0X%02X, reg_data = %d\n", idx, cfg->reg_addr[idx], reg_data);

    send_spi_data(  gpio_reg,
                    gpio2_reg,
                    gpio_in_reg,
                    spi_config, 
                    spi_data );

    spi_data_free( spi_data );

    return 0;    
}

void reset_ad9508( uint32_t *gpio_reg ){
    
    setbit(*gpio_reg, BIT_RESET_9508);

    usleep(1000);

    clrbit(*gpio_reg, BIT_RESET_9508);
    
    printf("> (ad9508) send a reset signal.\n");
}

void sync_ad9508( uint32_t *gpio_reg ){

    setbit(*gpio_reg, BIT_SYNC_9508);

    usleep(1000);

    clrbit(*gpio_reg, BIT_SYNC_9508);
    
    printf("> (ad9508) send a sync signal.\n");
}

